/**
 * @(#)SystemProcessAuthorityServiceImpl.java Aug 31, 2009
 *   
 * Copyright  (c) 2009-2010 Wilmar IT Service,  Inc.   
 * All  rights  reserved.   
 * TODO
 */

package com.wilmar.process.core.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import com.wilmar.process.core.ProcessSystemDeclareKeys;
import com.wilmar.process.core.services.api.ISystemProcessAuthorityService;
import com.wilmar.process.core.services.spi.IOrganizationService;
import com.wilmar.process.core.services.spi.IRoleService;
import com.wilmar.process.dao.api.IProcessAuthorityDAO;
import com.wilmar.process.entity.Organization;
import com.wilmar.process.entity.ProcessAuthority;
import com.wilmar.process.entity.Role;
import com.wilmar.process.entity.User;
import com.wilmar.process.entity.vo.ProcessAuthorityVO;
import com.wilmar.process.enumerate.EnumProcessAuthorityQueryParamNameSet;
import com.wilmar.process.enumerate.EnumProcessAuthorityType;
import com.wilmar.process.enumerate.EnumSystemQueryNameSet;
import com.wilmar.process.exception.DirtyDataException;
import com.wilmar.process.exception.PermissionDeniedException;

/**
 * @author MaKuBEX Email:makubexnet@gmail.com
 * @version 1.0.0
 */
public class SystemProcessAuthorityServiceImpl implements
		ISystemProcessAuthorityService {
	private IProcessAuthorityDAO processAuthorityDAO;
	private IRoleService roleService;
	private IOrganizationService organizationService;

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessAuthorityService#getListByProcessDefinitionKey(java.lang.String)
	 */
	public List<ProcessAuthority> getListByProcessDefinitionKey(
			String processDefinitionKey) {
		ProcessAuthority example = new ProcessAuthority();
		example.setProcessDefinitionKey(processDefinitionKey);
		return this.processAuthorityDAO.getListByExample(example);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessAuthorityService#getListByProcessDefinitionKeyAnyOuterSystem(java.lang.String,
	 *      java.lang.String)
	 */
	public List<ProcessAuthority> getListByProcessDefinitionKeyAndOuterSystem(
			String processDefinitionKey, String outerSystem) {
		ProcessAuthority example = new ProcessAuthority();
		example.setProcessDefinitionKey(processDefinitionKey);
		example.setOuterSystem(outerSystem);
		return this.processAuthorityDAO.getListByExample(example);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessAuthorityService#getListByUserInformation(com.wilmar.process.entity.User)
	 */
	public List<ProcessAuthority> getListByUserInformation(User user) {
		Set<Role> userRoles = this.roleService.getListRolesByUser(user);
		Set<Organization> userOrgs = this.organizationService
				.getListAllOrganizationsByUser(user);
		String[] paramNames = new String[] {
				EnumProcessAuthorityQueryParamNameSet.QUERY_PARAMETER_NAME_OUTERSYSTEM
						.getValue(),
				EnumProcessAuthorityQueryParamNameSet.QUERY_PARAMETER_NAME_ORGANIZATIONCODE
						.getValue(),
				EnumProcessAuthorityQueryParamNameSet.QUERY_PARAMETER_NAME_ROLECODE
						.getValue() };
		Object[] values = new Object[] { user.getOuterSystem(), userOrgs,
				userRoles };
		List<ProcessAuthority> list = this.processAuthorityDAO
				.getListByNamedQueryAndNamedParams(
						EnumSystemQueryNameSet.PROCESS_SYSTEM_QUERY_NAME_PROCESSAUTHORITY_GETAVAILABLELISTBYUSER,
						paramNames, values);
		return list;
	}

	public IProcessAuthorityDAO getProcessAuthorityDAO() {
		return processAuthorityDAO;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessAuthorityService#removeAllAuthorityByProcessDefinitionKey(java.lang.String)
	 */
	public void removeAllAuthorityByProcessDefinitionKey(
			String processDefinitionKey) {
		List<ProcessAuthority> all = this
				.getListByProcessDefinitionKey(processDefinitionKey);
		this.processAuthorityDAO.removeAll(all);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessAuthorityService#removeAllAuthorityByProcessDefinitionKeyAndOuterSystem(java.lang.String,
	 *      java.lang.String)
	 */
	public void removeAllAuthorityByProcessDefinitionKeyAndOuterSystem(
			String processDefinitionKey, String outerSystem) {
		List<ProcessAuthority> all = this
				.getListByProcessDefinitionKeyAndOuterSystem(
						processDefinitionKey, outerSystem);
		this.processAuthorityDAO.removeAll(all);
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessAuthorityService#saveAllAuthority(java.util.List)
	 */
	public void saveAllAuthority(List<ProcessAuthority> allAuthority) {
		this.processAuthorityDAO.saveOrUpdateAll(allAuthority);

	}

	/**
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVO(java.lang
	 *      .Object)
	 */
	public ProcessAuthorityVO convertToVO(ProcessAuthority entity) {
		ProcessAuthorityVO processAuthorityVO = new ProcessAuthorityVO(entity);
		return processAuthorityVO;
	}

	/**
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVOList(java
	 *      .util.List)
	 */
	public List<ProcessAuthorityVO> convertToVOList(
			Collection<ProcessAuthority> entityCollection) {
		ArrayList<ProcessAuthorityVO> voList = new ArrayList<ProcessAuthorityVO>(
				entityCollection.size());

		for (ProcessAuthority processAuthority : entityCollection) {
			voList.add(this.convertToVO(processAuthority));
		}

		return voList;
	}

	public void setProcessAuthorityDAO(IProcessAuthorityDAO processAuthorityDAO) {
		this.processAuthorityDAO = processAuthorityDAO;
	}

	/**
	 * @return the roleService
	 */
	public IRoleService getRoleService() {
		return roleService;
	}

	/**
	 * @param roleService
	 *            the roleService to set
	 */
	public void setRoleService(IRoleService roleService) {
		this.roleService = roleService;
	}

	/**
	 * @return the organizationService
	 */
	public IOrganizationService getOrganizationService() {
		return organizationService;
	}

	/**
	 * @param organizationService
	 *            the organizationService to set
	 */
	public void setOrganizationService(IOrganizationService organizationService) {
		this.organizationService = organizationService;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemProcessAuthorityService#validateStartAuthority(java.lang.String,
	 *      com.wilmar.process.entity.User)
	 */
	public void validateStartAuthority(String processDefinitionKey, User user)
			throws PermissionDeniedException, DirtyDataException {
		List<ProcessAuthority> allAuthority = this
				.getListByProcessDefinitionKeyAndOuterSystem(
						processDefinitionKey, user.getOuterSystem());
		boolean flag = false;
		if (allAuthority == null || allAuthority.isEmpty()) {
			throw new DirtyDataException("The process definition named: "
					+ processDefinitionKey + " had not been authorized!");
		}
		Set<Role> userRoles = this.roleService.getListRolesByUser(user);
		Set<Organization> userOraganizations = this.organizationService
				.getListAllOrganizationsByUser(user);
		for (ProcessAuthority processAuthority : allAuthority) {
			if (EnumProcessAuthorityType.PROCESS_SYSTEM_DEFINITION_AUTHORITY_TYPE_BOTH
					.equals(processAuthority.getAuthorizeType())) {
				String roleCode = processAuthority.getRoleCode();
				String orgCode = processAuthority.getOrganizationCode();
				Role roleObj = new Role(
						user.getOuterSystem()
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_USER_OUTERSYSTEM_SEPTATOR
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_PROCESS_ASSIGN_MARK_ROLE
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_USER_OUTERSYSTEM_SEPTATOR
								+ roleCode);
				Organization orgObj = new Organization(
						user.getOuterSystem()
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_USER_OUTERSYSTEM_SEPTATOR
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_PROCESS_ASSIGN_MARK_ORGANIZATION
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_USER_OUTERSYSTEM_SEPTATOR
								+ orgCode);
				if (userRoles.contains(roleObj)
						&& userOraganizations.contains(orgObj)) {
					flag = true;
					break;
				}
			} else if (EnumProcessAuthorityType.PROCESS_SYSTEM_DEFINITION_AUTHORITY_TYPE_ORGANIZATION
					.equals(processAuthority.getAuthorizeType())) {
				String orgCode = processAuthority.getOrganizationCode();
				Organization orgObj = new Organization(
						user.getOuterSystem()
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_USER_OUTERSYSTEM_SEPTATOR
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_PROCESS_ASSIGN_MARK_ORGANIZATION
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_USER_OUTERSYSTEM_SEPTATOR
								+ orgCode);
				if (userOraganizations.contains(orgObj)) {
					flag = true;
					break;
				}
			} else if (EnumProcessAuthorityType.PROCESS_SYSTEM_DEFINITION_AUTHORITY_TYPE_ROLE
					.equals(processAuthority.getAuthorizeType())) {
				String roleCode = processAuthority.getRoleCode();
				Role roleObj = new Role(
						user.getOuterSystem()
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_USER_OUTERSYSTEM_SEPTATOR
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_PROCESS_ASSIGN_MARK_ROLE
								+ ProcessSystemDeclareKeys.PROCESS_SYSTEM_USER_OUTERSYSTEM_SEPTATOR
								+ roleCode);
				if (userRoles.contains(roleObj)) {
					flag = true;
					break;
				}
			} else {
				throw new DirtyDataException(
						"There are some dirty data in the process definition authroity table!");
			}
		}
		if (!flag)
			throw new PermissionDeniedException("You can't start this process!");

	}

}
